package com.hczx.caxa.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hczx.caxa.bean.SignInfoBean;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class TechnicalGeneratePdfService {

    private static final Object JSONArray = null;

	private static Logger logger = LoggerFactory.getLogger(TechnicalGeneratePdfService.class);

    private final MinioService minioService;
    private final LogFileService logFile;

	private static Font HEAD_FONT;
	private static Font FONT;
	private static Font SMALL_FONT;
	
	public TechnicalGeneratePdfService(MinioService minioService, LogFileService logFile) {
        this.minioService = minioService;
        this.logFile = logFile;
    }
	
	static{
		try {
			String fontPath = "/fonts/simsun.ttc,1";
			BaseFont BASE_FONT = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			SMALL_FONT = new Font(BASE_FONT, 10, Font.NORMAL);
			FONT = new Font(BASE_FONT, 12, Font.NORMAL);
			HEAD_FONT = new Font(BASE_FONT, 18, Font.BOLD);
		} catch (DocumentException | IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 设计更改单生成逻辑
	 * @param loggerBuffer
	 * @param basicInfo
	 * @param number
	 * @param changeContent
	 * @param effect
	 * @param reason
	 * @param signInfo
	 * @param sendDepartment
	 * @param model
	 * @param imageName
	 * @param images
	 * @return
	 * @throws Exception
	 */
    public String doGeneratePdf(StringBuffer loggerBuffer, String basicInfo, String number, Object changeContent,
    		String effect, String reason, Object signInfo, String sendDepartment, String model, 
    		String imageName, Map<String, MultipartFile> images) throws Exception {
    	
        String targetPath = StringUtils.EMPTY;
        loggerBuffer.append(logFile.now()).append("  -->开始执行转PDF......").append("\n");

        try {
            //生成PDF文件
            ByteArrayOutputStream outputStream = writePRContent(basicInfo, number, changeContent, effect, 
            		reason, signInfo, sendDepartment, model, imageName, images);
            
            String targetName = "/generatePdf/generatePdf_" + number + ".pdf";
            
            loggerBuffer.append(logFile.now()).append("  -->开始上传Minio").append("\n");
            loggerBuffer.append(logFile.now()).append("  -->上传Minio位置：").append(targetName).append("\n");

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
            targetPath = minioService.upload(byteArrayInputStream, targetName, "application/pdf");

            loggerBuffer.append(logFile.now()).append("  -->上传Minio地址:").append("\n");
            loggerBuffer.append(logFile.now()).append(targetPath).append("\n");

        } catch (Exception e) {
            logger.error("生成PDF出错，详情请查看日志！\n", e);
            throw new Exception("生成PDF出错，详情请查看日志！");
        }
        return targetPath;
    }
    
    /**
     * 生成设计更改单PDF
     * @param basicInfo
     * @param number
     * @param changeContent
     * @param effect
     * @param reason
     * @param signInfo
     * @param sendDepartment
     * @param model
     * @param imageName
     * @param images
     * @return
     * @throws Exception
     */
	public ByteArrayOutputStream writePRContent(String basicInfo, String number, Object changeContent,
    		String effect, String reason, Object signInfo, String sendDepartment, String model, 
    		String imageName, Map<String, MultipartFile> images) throws Exception {
		//各图片对应的缩小倍数map
		Map<String, Float> reductionFactor = Maps.newHashMap();
		//确定总页数
		int page = 1;
		//存放每一页写入哪几条内容
		Map<Integer, List<Integer>> infoMap = Maps.newHashMap();
		List<Integer> preInfoList = Lists.newArrayList();
		List<Integer> afterInfoList = Lists.newArrayList();
		float preHeight = 240;
		float afterHeight = 240;
		//记录换页逻辑
		boolean flag = true;
		JSONArray changeContentArray = (JSONArray) changeContent;
		for (int orderNumber = 0; orderNumber < changeContentArray.size(); orderNumber++) {
			Object object = changeContentArray.get(orderNumber);
			JSONObject json = (JSONObject) object;
			for (String key : json.keySet()) {
				logger.info("最早的page:{}", page);
				if(StringUtils.contains(key, "preChangeContent")) {
					String str = (orderNumber+1)+"."+json.get(key);
					BigDecimal preCharactersLength = new BigDecimal(str.length());
					BigDecimal rows = preCharactersLength.divide(new BigDecimal("17"), 0, RoundingMode.UP);
					float rowsValue = rows.multiply(new BigDecimal(13)).floatValue();
					logger.info("preRowsValue:{}", rowsValue);
					float height = 0;
					logger.info("最早的orderNumber+1:{}", orderNumber+1);
					MultipartFile multipartFile = images.get("preChangeContent"+ (orderNumber+1));
					if(multipartFile != null) {
						logger.info("有图，进来了");
				        byte[] imageBytes = multipartFile.getBytes();
				        Image image = Image.getInstance(imageBytes);
				        //缩小倍数
				        float times = 1;
				        BigDecimal imageWidth = new BigDecimal(image.getWidth());
				        BigDecimal imageHeight = new BigDecimal(image.getHeight());
				        BigDecimal widthTimesByBigDecimal = imageWidth.divide(new BigDecimal("220"), 1, RoundingMode.HALF_UP);
				        BigDecimal heightTimesByBigDecimal = imageHeight.divide(new BigDecimal(preHeight-rowsValue), 1, RoundingMode.HALF_UP);
				        //对比得到最大缩小倍数值
				        BigDecimal timesByBigDecimal = widthTimesByBigDecimal.compareTo(heightTimesByBigDecimal) > -1 ?
				        		widthTimesByBigDecimal : heightTimesByBigDecimal;
				        //如果此倍数值大于1，则需要对图片进行缩小
				        if(timesByBigDecimal.compareTo(new BigDecimal(1)) == 1) {
				        	times = timesByBigDecimal.floatValue();
				        }
				        reductionFactor.put("preChangeContent"+ (orderNumber+1), times);
				        height = (float) image.getHeight()/times + 13;//此13为换行预留空间
					}
					logger.info("imageHeight:{}", height);
					preHeight = preHeight - (rowsValue + height);
					logger.info("rowsValue + height:{}", rowsValue + height);
					logger.info("本页剩余高度容量preHeight:{}", preHeight);
					if(preHeight < 0 && preInfoList.isEmpty()) {
						if(flag) {
							flag = false;
							logger.info("空间不足，但强制插入了preInfoList一次数据。");
							preHeight = 240;
							afterHeight = 240;
							preInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							for (Integer integer : preInfoList) {
								logger.info("preInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							if((orderNumber+1) < changeContentArray.size()) page += 1;
							continue;
						}
					}else if(preHeight < 0) {
						if(flag) {
							flag = false;
							logger.info("本页空间不足，跳转至下一页");
							preHeight = 240;
							afterHeight = 240;
							List<Integer> list = Lists.newArrayList();
							preInfoList = preInfoList.size() >= afterInfoList.size() 
									? afterInfoList : preInfoList;
							for (Integer integer : preInfoList) {
								logger.info("preInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							page += 1;
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							orderNumber -= 1;
							continue;
						}
					}else if((orderNumber+1) >= changeContentArray.size()) {
						if(flag) {
							flag = false;
							logger.info("没有下一条内容了，直接插入");
							preInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							preInfoList = preInfoList.size() >= afterInfoList.size() 
									? preInfoList : afterInfoList;
							for (Integer integer : preInfoList) {
								logger.info("preInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							continue;
						}
					}else if(preHeight >= 0) {
						logger.info("空间充裕，插入了preInfoList一次数据。");
						preInfoList.add(orderNumber+1);
					}
				}else if(StringUtils.contains(key, "afterChangeContent")) {
					String str = (orderNumber+1)+"."+json.get(key);
					BigDecimal preCharactersLength = new BigDecimal(str.length());
					BigDecimal rows = preCharactersLength.divide(new BigDecimal("17"), 0, RoundingMode.UP);
					float rowsValue = rows.multiply(new BigDecimal(13)).floatValue();
					logger.info("afterRowsValue:{}", rowsValue);
					float height = 0;
					logger.info("最早的orderNumber+1:{}", orderNumber+1);
					MultipartFile multipartFile = images.get("afterChangeContent"+ (orderNumber+1));
					if(multipartFile != null) {
						logger.info("有图，进来了");
				        byte[] imageBytes = multipartFile.getBytes();
				        Image image = Image.getInstance(imageBytes);
				        //缩小倍数
				        float times = 1;
				        BigDecimal imageWidth = new BigDecimal(image.getWidth());
				        BigDecimal imageHeight = new BigDecimal(image.getHeight());
				        BigDecimal widthTimesByBigDecimal = imageWidth.divide(new BigDecimal("220"), 1, RoundingMode.HALF_UP);
				        BigDecimal heightTimesByBigDecimal = imageHeight.divide(new BigDecimal(afterHeight-rowsValue), 1, RoundingMode.HALF_UP);
				        //对比得到最大缩小倍数值
				        BigDecimal timesByBigDecimal = widthTimesByBigDecimal.compareTo(heightTimesByBigDecimal) > -1 ?
				        		widthTimesByBigDecimal : heightTimesByBigDecimal;
				        //如果此倍数值大于1，则需要对图片进行缩小
				        if(timesByBigDecimal.compareTo(new BigDecimal(1)) == 1) {
				        	times = timesByBigDecimal.floatValue();
				        }
				        reductionFactor.put("afterChangeContent"+ (orderNumber+1), times);
				        height = (float) image.getHeight()/times + 13;//此13为换行预留空间
					}
					logger.info("imageHeight:{}", height);
					afterHeight = afterHeight - (rowsValue + height);
					logger.info("rowsValue + height:{}", rowsValue + height);
					logger.info("本页剩余高度容量afterHeight:{}", afterHeight);
					if(afterHeight < 0 && afterInfoList.isEmpty()) {
						if(flag) {
							flag = false;
							logger.info("空间不足，但强制插入了afterInfoList一次数据。");
							preHeight = 240;
							afterHeight = 240;
							afterInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							for (Integer integer : afterInfoList) {
								logger.info("afterInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							if((orderNumber+1) < changeContentArray.size()) page += 1;
							continue;
						}
					}else if(afterHeight < 0) {
						if(flag) {
							flag = false;
							logger.info("本页空间不足，跳转至下一页");
							preHeight = 240;
							afterHeight = 240;
							List<Integer> list = Lists.newArrayList();
							afterInfoList = preInfoList.size() >= afterInfoList.size() 
									? afterInfoList : preInfoList;
							for (Integer integer : afterInfoList) {
								logger.info("afterInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							page += 1;
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							orderNumber -= 1;
							continue;
						}
					}else if((orderNumber+1) >= changeContentArray.size()) {
						if(flag) {
							flag = false;
							logger.info("没有下一条内容了，直接插入");
							afterInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							afterInfoList = preInfoList.size() >= afterInfoList.size() 
									? preInfoList : afterInfoList;
							for (Integer integer : afterInfoList) {
								logger.info("afterInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							continue;
						}
					}else if(afterHeight >= 0) {
						logger.info("空间充裕，插入了afterInfoList一次数据。");
						afterInfoList.add(orderNumber+1);
					}
				}
    		}
			flag = true;
		}
		
		for (Integer integer : infoMap.keySet()) {
			List<Integer> list = infoMap.get(integer);
			for (Integer i : list) {
				logger.info("infoMap:{}", "第"+integer+"页中需要写入的条目为"+i);
			}
		}
		
		for (String str : reductionFactor.keySet()) {
			float float1 = reductionFactor.get(str);
			logger.info("reductionFactor:{}", "图片"+str+"的缩放比例为"+float1);
		}
		
		//分发部门获取
		String scbgyz = "生产部工艺组 □";
		String zlb = "质量部 □";
		String gylb = "供应链部 □";
		String scb = "市场部 □";
		int phr = 0;
		if(StringUtils.isNotEmpty(sendDepartment)) {
			String[] split = sendDepartment.split("\\|");
			for (String str : split) {
				if(str.contains("生产部")) {
					scbgyz = "生产部工艺组 ■";
					phr += 1;
				}else if(str.contains("质量部")) {
					zlb = "质量部 ■";
					phr += 1;
				}else if(str.contains("采购部")) {
					gylb = "供应链部 ■";
					phr += 1;
				}else if(str.contains("市场部")) {
					scb = "市场部 ■";
					phr += 1;
				}
			}
		}
		
		//基本信息获取
		String changeNumber = "";
		String changeName = "";
		String changeCategory = "";
		String stage = "";
		if(StringUtils.isNotEmpty(basicInfo)) {
			String[] split = basicInfo.split("\\|");
			changeNumber = split[0];
			changeName = split[1];
			changeCategory = split[2];
			stage = split[3];
		}
		
		//签名信息获取
		String sd = "";
		String sdsj = "";
		String pz = "";
		String pzsj = "";
		String sc = "";
		String scsj = "";
		String zl = "";
		String zlsj = "";
		String jd = "";
		String jdsj = "";
		String gy = "";
		String gysj = "";
		String bz = "";
		String bzsj = "";
		String bs = "";
		String bssj = "";
		for (Object object : (JSONArray) signInfo) {
			JSONObject json = (JSONObject) object;
			for (String key : json.keySet()) {
				String str = (String) json.get(key);
				String[] split = str.split("\\|");
				switch (key) {
				case "sd":
					sd = split[0];
					sdsj = split[1];
					break;
				case "pz":
					pz = split[0];
					pzsj = split[1];
					break;
				case "sc":
					sc = split[0];
					scsj = split[1];
					break;
				case "zl":
					zl = split[0];
					zlsj = split[1];
					break;
				case "jd":
					jd = split[0];
					jdsj = split[1];
					break;
				case "gy":
					gy = split[0];
					gysj = split[1];
					break;
				case "bz":
					bz = split[0];
					bzsj = split[1];
					break;
				case "bs":
					bs = split[0];
					bssj = split[1];
					break;
				}
    		}
		}
		
		//开始生成PDF
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		Document document = new Document();
    	document.setPageSize(PageSize.A4);
		PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
		
		document.open();
		
		logger.info("page:{}", page);
		for(int i = 1; i <= page; i++) {
			PdfContentByte cb = pdfWriter.getDirectContent();
			cb.setLineWidth(0.2f);  // 设置线宽
			cb.moveTo(document.left(30f), document.top());  // 将画笔移动到左上角
			cb.lineTo(document.right(30f), document.top());  // 画横线
			cb.setLineWidth(1f);
			cb.stroke();  // 绘制线条
	        
			Paragraph header = new Paragraph("设计更改单", HEAD_FONT);
			header.setAlignment(Element.ALIGN_CENTER);
			document.add(header);
			
			header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph(" 文件编号：FR090301-02", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			PdfPTable table = new PdfPTable(18);
			float[] cellsWidth = {39f, 39f, 59f, 48f, 38f, 14f, 22f, 12f, 16f, 12f, 32f, 10f, 28f, 10f, 28f, 20f, 25f, 45f};
			table.setWidths(cellsWidth);// 单元格宽度
			table.setSplitLate(false);
			table.setWidthPercentage(100);
			
			PdfPCell sendDepartmentCell = createCell("发送至：\n\n"+scbgyz+"\n\n"+zlb+"\n\n"+gylb+"\n\n"+scb+"\n\n共 "+phr+" 份"
					+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n 会签", 
					0, 2, 7, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT);
			table.addCell(sendDepartmentCell);
			
			//插入航星logo图片
			String logoPath = "images/logo.png";
			URL logoUrl = getClass().getClassLoader().getResource(logoPath);
			PdfPCell logoCell = createCell("", 0, 1, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT);
			Image logo = Image.getInstance(logoUrl);
			logo.scaleAbsolute((float)(logo.getWidth()*0.05), (float)(logo.getHeight()*0.05));
			logoCell.addElement(logo);
			table.addCell(logoCell);
			
			table.addCell(createCell("更改类别", 0, 1, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(changeCategory, 0, 1, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("第 "+changeNumber+" 号", 0, 6, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("缓急程度", 0, 2, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("共"+page+"页", 19f, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("第"+i+"页", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("附图：0页", 39f, 3, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("型 号", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("更改图号或文件号", 0, 4, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("名称", 0, 3, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(changeName, 0, 5, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("阶段", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(stage, 20f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(model, 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(number, 0, 4, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("发新图：0 页", 31f, 3, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("第 1 次修改", 19f, 5, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			//更改内容获取
			Paragraph preParagraph = new Paragraph();
			Paragraph afterParagraph = new Paragraph();
			Chunk preChunk = new Chunk("更改前：\n");
			preChunk.setFont(FONT);
			preParagraph.add(preChunk);
			Chunk afterChunk = new Chunk("更改后：\n");
			afterChunk.setFont(FONT);
	        afterParagraph.add(afterChunk);
	        //获取到本页需要写入哪几条更改内容
	        List<Integer> list = infoMap.get(i);
	        logger.info("i:{}", i);
	        for (Integer integer : list) {
				for (Object object : (JSONArray) changeContent) {
					JSONObject json = (JSONObject) object;
					for (String key : json.keySet()) {
						if(StringUtils.equals(key, "preChangeContent"+integer)) {
							preChunk = new Chunk(integer+"."+json.get(key)+"\n");
							preChunk.setFont(FONT);
							preParagraph.add(preChunk);
							MultipartFile multipartFile = images.get("preChangeContent"+ integer);
							if(multipartFile != null) {
						        //获取图片的字节数组
						        byte[] imageBytes = multipartFile.getBytes();
						        //创建Image对象并将字节数组作为参数传递
						        Image image = Image.getInstance(imageBytes);
						        //获取缩小倍数
						        logger.info("获取比例preChangeContent:{}", "preChangeContent"+ integer);
						        float times = reductionFactor.get("preChangeContent"+ integer);
						        image.scaleToFit((float)(image.getWidth()/times), (float) image.getHeight()/times);
						        //插入图片至表格中
								preParagraph.add(new Chunk(image, 0, 0, true));
								//换行
								preChunk = new Chunk("\n");
								preParagraph.add(preChunk);
							}
						}else if(StringUtils.equals(key, "afterChangeContent"+integer)) {
							afterChunk = new Chunk(integer+"."+json.get(key)+"\n");
							afterChunk.setFont(FONT);
					        afterParagraph.add(afterChunk);
							MultipartFile multipartFile = images.get("afterChangeContent"+ integer);
							if(multipartFile != null) {
						        //获取图片的字节数组
						        byte[] imageBytes = multipartFile.getBytes();
						        //创建Image对象并将字节数组作为参数传递
						        Image image = Image.getInstance(imageBytes);
						        //获取缩小倍数
						        logger.info("获取比例afterChangeContent:{}", "afterChangeContent"+ integer);
						        float times = reductionFactor.get("afterChangeContent"+ integer);
						        image.scaleToFit((float)(image.getWidth()/times), (float) image.getHeight()/times);
						        //插入图片至表格中
						        afterParagraph.add(new Chunk(image, 0, 0, true));
						        //换行
						        afterChunk = new Chunk("\n");
						        afterParagraph.add(afterChunk);
							}
						}
		    		}
				}
			}
	        
			table.addCell(createCell("更改序号", 0, 6, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			if(list.size() > 1) {
				table.addCell(createCell(list.get(0)+"-"+list.get(list.size()-1), 0, 5, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			}else {
				table.addCell(createCell(list.get(0)+"", 0, 5, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			}
			
			PdfPCell preCell = createCell("", 300f, 7, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT);
			preCell.addElement(preParagraph);
			table.addCell(preCell);
			
			PdfPCell afterCell = createCell("", 0, 9, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT);
			afterCell.addElement(afterParagraph);
			table.addCell(afterCell);
			
			table.addCell(createCell("对制品的影响", 94f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(effect, 0, 15, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("更改原因", 47f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(reason, 0, 15, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT));
			
			table.addCell(createCell("", 0, 1, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("生效日期", 0, 1, 4, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 4, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("审定", 21f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(sd, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(sdsj, 0, 4, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("批准", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(pz, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(pzsj, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("审查", 21f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(sc, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(scsj, 0, 4, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("质量", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(zl, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(zlsj, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 2, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 2, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("校对", 21f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(jd, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(jdsj, 0, 4, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("工艺", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(gy, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(gysj, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("编制", 21f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(bz, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(bzsj, 0, 4, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("标审", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(bs, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(bssj, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			document.add(table);
			//有下一页，新生成一页PDF
			if(i+1 <= page) {
				document.newPage();
			}
		}
		
		document.close();
		
		return baos;
	}

	/**
	 * 技术通知单生成逻辑
	 * @param loggerBuffer
	 * @param number
	 * @param name
	 * @param model
	 * @param content
	 * @param validPeriod
	 * @param signInfo
	 * @param sendDepartment
	 * @return
	 * @throws Exception
	 */
	public String doTechnicalNoticePdf(StringBuffer loggerBuffer, String number, String name, String model,
			Object content, String validPeriod, Object signInfo, String sendDepartment, 
    		Map<String, MultipartFile> images) throws Exception {
    	
        String targetPath = StringUtils.EMPTY;
        loggerBuffer.append(logFile.now()).append("  -->开始执行转PDF......").append("\n");

        try {
            //生成PDF文件
            ByteArrayOutputStream outputStream = writeTNContent(number, name, model, content, 
            		validPeriod, signInfo, sendDepartment, images);
            
            String targetName = "/generateTechnicalNoticePdf/generateTechnicalNoticePdf_" + number + ".pdf";
            
            loggerBuffer.append(logFile.now()).append("  -->开始上传Minio").append("\n");
            loggerBuffer.append(logFile.now()).append("  -->上传Minio位置：").append(targetName).append("\n");

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
            targetPath = minioService.upload(byteArrayInputStream, targetName, "application/pdf");

            loggerBuffer.append(logFile.now()).append("  -->上传Minio地址:").append("\n");
            loggerBuffer.append(logFile.now()).append(targetPath).append("\n");

        } catch (Exception e) {
            logger.error("生成PDF出错，详情请查看日志！\n", e);
            throw new Exception("生成PDF出错，详情请查看日志！");
        }
        return targetPath;
    }
	
	/**
	 * 生成技术通知单PDF
	 * @param number
	 * @param name
	 * @param model
	 * @param content
	 * @param validPeriod
	 * @param signInfo
	 * @param sendDepartment
	 * @return
	 * @throws Exception
	 */
	public ByteArrayOutputStream writeTNContent(String number, String name, String model,
			Object content, String validPeriod, Object signInfo, String sendDepartment, 
    		Map<String, MultipartFile> images) throws Exception {
		//各图片对应的缩小倍数map
		Map<String, Float> reductionFactor = Maps.newHashMap();
		//确定总页数
		int page = 1;
		//存放每一页写入哪几条内容
		Map<Integer, List<Integer>> infoMap = Maps.newHashMap();
		List<Integer> infoList = Lists.newArrayList();
		float height = 450;
		JSONArray contentArray = (JSONArray) content;
		Object obj = contentArray.get(0);
		JSONObject contentJson = (JSONObject) obj;
		Set<String> keySet = contentJson.keySet();
		List<String> keyList = Lists.newArrayList();
		for (String key : keySet) {
			keyList.add(key);
		}
		for (int orderNumber = 1;orderNumber <= keySet.size(); orderNumber++) {
			String key = keyList.get(orderNumber-1);
			String str = orderNumber+"."+contentJson.get(key);
			BigDecimal charactersLength = new BigDecimal(str.length());
			BigDecimal rows = charactersLength.divide(new BigDecimal("35"), 0, RoundingMode.UP);
			float rowsValue = rows.multiply(new BigDecimal(13)).floatValue();
			float imageHeight = 0;
			MultipartFile multipartFile = images.get("content"+ orderNumber);
			if(multipartFile != null) {
				logger.info("有图，进来了");
		        byte[] imageBytes = multipartFile.getBytes();
		        Image image = Image.getInstance(imageBytes);
		        //缩小倍数
		        float times = 1;
		        BigDecimal imageWidth = new BigDecimal(image.getWidth());
		        BigDecimal imageHeight1 = new BigDecimal(image.getHeight());
		        BigDecimal widthTimesByBigDecimal = imageWidth.divide(new BigDecimal("440"), 3, RoundingMode.HALF_UP);
		        BigDecimal heightTimesByBigDecimal = imageHeight1.divide(new BigDecimal(height-rowsValue), 1, RoundingMode.HALF_UP);
		        //对比得到最大缩小倍数值
		        BigDecimal timesByBigDecimal = widthTimesByBigDecimal.compareTo(heightTimesByBigDecimal) > -1 ?
		        		widthTimesByBigDecimal : heightTimesByBigDecimal;
		        //如果此倍数值大于1，则需要对图片进行缩小
		        if(timesByBigDecimal.compareTo(new BigDecimal(1)) == 1) {
		        	times = timesByBigDecimal.floatValue();
		        }
		        reductionFactor.put("content"+ orderNumber, times);
		        imageHeight = (float) image.getHeight()/times + 13;//此13为换行预留空间
			}
			logger.info("imageHeight:{}", imageHeight);
			height = height - (rowsValue + imageHeight);
			logger.info("本页剩余高度容量height:{}", height);
			if(height < 0 && infoList.isEmpty()) {
				logger.info("空间不足，但强制插入了infoList一次数据。");
				height = 450;
				infoList.add(orderNumber);
				List<Integer> list = Lists.newArrayList();
				for (Integer integer : infoList) {
					list.add(integer);
				}
				infoMap.put(page, list);
				infoList = Lists.newArrayList();
				if((orderNumber+1) <= keySet.size()) page += 1;
			}else if(height < 0) {
				logger.info("本页空间不足，跳转至下一页");
				height = 450;
				List<Integer> list = Lists.newArrayList();
				for (Integer integer : infoList) {
					list.add(integer);
				}
				infoMap.put(page, list);
				page += 1;
				infoList = Lists.newArrayList();
				orderNumber -= 1;
			}else if((orderNumber+1) > keySet.size()) {
				logger.info("没有下一条内容了，直接插入");
				infoList.add(orderNumber);
				List<Integer> list = Lists.newArrayList();
				for (Integer integer : infoList) {
					list.add(integer);
				}
				infoMap.put(page, list);
			}else if(height >= 0) {
				logger.info("空间充裕，插入了infoList一次数据。");
				infoList.add(orderNumber);
			}
		}
		
		//分发部门获取
		String scb = "生产部 □";
		String zlb = "质量部 □";
		String gylb = "供应链部 □";
		int phr = 0;
		if(StringUtils.isNotEmpty(sendDepartment)) {
			String[] split = sendDepartment.split("\\|");
			for (String str : split) {
				if(str.contains("生产部")) {
					scb = "生产部 ■";
					phr += 1;
				}else if(str.contains("质量部")) {
					zlb = "质量部 ■";
					phr += 1;
				}else if(str.contains("采购部")) {
					gylb = "供应链部 ■";
					phr += 1;
				}
			}
		}
		
		//签名信息获取
		String bz = "";
		String bzsj = "";
		String jd = "";
		String jdsj = "";
		String sh = "";
		String shsj = "";
		String bs = "";
		String bssj = "";
		String pz = "";
		String pzsj = "";
		for (Object object : (JSONArray) signInfo) {
			JSONObject json = (JSONObject) object;
			for (String key : json.keySet()) {
				String str = (String) json.get(key);
				String[] split = str.split("\\|");
				switch (key) {
				case "bz":
					bz = split[0];
					bzsj = split[1];
					break;
				case "jd":
					jd = split[0];
					jdsj = split[1];
					break;
				case "sh":
					sh = split[0];
					shsj = split[1];
					break;
				case "bs":
					bs = split[0];
					bssj = split[1];
					break;
				case "pz":
					pz = split[0];
					pzsj = split[1];
					break;
				}
    		}
		}
		
		//开始生成PDF
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		Document document = new Document();
    	document.setPageSize(PageSize.A4);
		PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
		
		document.open();
		
		logger.info("page:{}", page);
		for(int i = 1; i <= page; i++) {
			PdfContentByte cb = pdfWriter.getDirectContent();
			cb.setLineWidth(0.2f);  // 设置线宽
			cb.moveTo(document.left(30f), document.top());  // 将画笔移动到左上角
			cb.lineTo(document.right(30f), document.top());  // 画横线
			cb.setLineWidth(1f);
			cb.stroke();  // 绘制线条
	        
			Paragraph header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph(" 文件编号：FR090302-02", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			PdfPTable table = new PdfPTable(12);
			float[] cellsWidth = {39f, 39f, 34f, 4f, 57f, 43f, 38f, 100f, 19f, 19f, 41f, 60f};
			table.setWidths(cellsWidth);// 单元格宽度
			table.setSplitLate(false);
			table.setWidthPercentage(100);
			
			PdfPCell sendDepartmentCell = createCell("发送至：\n\n"+scb+"\n\n"+zlb+"\n\n"+gylb+"\n\n共 "+phr+" 份"
					+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n 会签栏", 
					0, 2, 5, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT);
			table.addCell(sendDepartmentCell);
			
			table.addCell(createCell("", 16f, 10, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			//插入航星logo图片
			String logoPath = "images/logo.png";
			URL logoUrl = getClass().getClassLoader().getResource(logoPath);
			PdfPCell logoCell = createCell("", 40f, 3, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT);
			Image logo = Image.getInstance(logoUrl);
			logo.scaleAbsolute((float)(logo.getWidth()*0.05), (float)(logo.getHeight()*0.05));
			//设置图片居中
			logo.setAlignment(Image.ALIGN_CENTER);
			logoCell.addElement(logo);
			table.addCell(logoCell);
			
			table.addCell(createCell("技\u0020\u0020术\u0020\u0020通\u0020\u0020知\u0020\u0020单", 
					0, 4, 2, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, HEAD_FONT));
			
			table.addCell(createCell(number, 0, 3, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("型别", 20f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(model, 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("共 1 页", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("第 1 页", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("标题", 20f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("关于"+name+"的通知", 0, 9, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			//更改内容获取
			Paragraph paragraph = new Paragraph();
	        //获取到本页需要写入哪几条内容
	        List<Integer> list = infoMap.get(i);
	        for (Integer integer : list) {
				for (Object object : (JSONArray) content) {
					JSONObject json = (JSONObject) object;
					for (String key : json.keySet()) {
						if(StringUtils.equals(key, "content"+integer)) {
							Chunk chunk = new Chunk(integer+"."+json.get(key)+"\n");
							chunk.setFont(FONT);
							paragraph.add(chunk);
							MultipartFile multipartFile = images.get("content"+ integer);
							if(multipartFile != null) {
						        //获取图片的字节数组
						        byte[] imageBytes = multipartFile.getBytes();
						        //创建Image对象并将字节数组作为参数传递
						        Image image = Image.getInstance(imageBytes);
						        //获取缩小倍数
						        float times = reductionFactor.get("content"+ integer);
						        image.scaleToFit((float)(image.getWidth()/times), (float) image.getHeight()/times);
						        image.setAlignment(Image.ALIGN_CENTER);
						        //插入图片至表格中
						        paragraph.add(new Chunk(image, 0, 0, true));
								//换行
						        chunk = new Chunk("\n");
								paragraph.add(chunk);
							}
						}
		    		}
				}
			}
			
	        PdfPCell preCell = createCell("", 468f, 10, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT);
			preCell.addElement(paragraph);
			table.addCell(preCell);
			
			table.addCell(createCell("", 40f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("有效期限/批次/台份："+validPeriod, 0, 10, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT));
			
			table.addCell(createCell("", 40f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("编制", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(bz+" "+bzsj, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("审核", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(sh+" "+shsj, 0, 1, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("批准", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(pz+" "+pzsj, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 40f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("校对", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(jd+" "+jdsj, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("标审", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(bs+" "+bssj, 0, 1, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			document.add(table);
			//有下一页，新生成一页PDF
			if(i+1 <= page) {
				document.newPage();
			}
		}
		
		document.close();
		
		return baos;
	}
	
	
	/**
	 * 创建单元格
	 * @param content
	 * @param fixedHeight
	 * @param colspan
	 * @param rowspan
	 * @param align
	 * @param isCenter
	 * @param font
	 * @return
	 */
	private static PdfPCell createCell(String content, float fixedHeight, int colspan, 
			int rowspan, int leftOrRight, int topOrUnder, Font font){
		PdfPCell cell = new PdfPCell(new Phrase(content, font));
		if(fixedHeight>0) {
			cell.setFixedHeight(fixedHeight);
		}
		cell.setColspan(colspan);
		cell.setRowspan(rowspan);
		cell.setLeading(1.5f, 1f);
		cell.setHorizontalAlignment(leftOrRight);
		cell.setVerticalAlignment(topOrUnder);
		return cell;
	}
	
	
	public String signOrderTechnicalWord(StringBuffer loggerBuffer, String number, String name,
			Object signInfo, String sendDepartment, MultipartFile wordFile) throws Exception {
    	
        String targetPath = StringUtils.EMPTY;
        loggerBuffer.append(logFile.now()).append("  -->开始执行签名......").append("\n");

        try (InputStream inputStream = wordFile.getInputStream();
	             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();) {
        	//获取签名信息
        	String bz = "";
    		String bzsj = "";
    		String jd = "";
    		String jdsj = "";
    		String sh = "";
    		String shsj = "";
    		String bs = "";
    		String bssj = "";
    		JSONArray jsonArray = new JSONArray();
    		String pz = "";
    		String pzsj = "";
    		for (Object object : (JSONArray) signInfo) {
    			JSONObject json = (JSONObject) object;
    			for (String key : json.keySet()) {
    				//解析会签
    				if(StringUtils.equals(key, "hq")) {
    					Object obj = json.get(key);
    					jsonArray = (JSONArray) obj;
    				}else {
    					String str = (String) json.get(key);
        				String[] split = str.split("\\|");
        				switch (key) {
        				case "bz":
        					bz = split[0];
        					bzsj = split[1];
        					break;
        				case "jd":
        					jd = split[0];
        					jdsj = split[1];
        					break;
        				case "sh":
        					sh = split[0];
        					shsj = split[1];
        					break;
        				case "bs":
        					bs = split[0];
        					bssj = split[1];
        					break;
        				case "pz":
        					pz = split[0];
        					pzsj = split[1];
        					break;
        				}
    				}
        		}
    		}
    		//记录会签栏所有格子的坐标
        	Map<Integer, String> hqCoordinateMap = Maps.newHashMap();
        	hqCoordinateMap.put(1, "4,0|4,1");
        	hqCoordinateMap.put(2, "5,0|5,1");
        	hqCoordinateMap.put(3, "6,0|6,1");
        	hqCoordinateMap.put(4, "7,0|7,1");
        	hqCoordinateMap.put(5, "8,0|8,1");
        	hqCoordinateMap.put(6, "9,0|9,1");
        	hqCoordinateMap.put(7, "10,0|10,1");
        	hqCoordinateMap.put(8, "4,2|4,3");
        	hqCoordinateMap.put(9, "5,2|5,3");
        	hqCoordinateMap.put(10, "6,2|6,3");
        	hqCoordinateMap.put(11, "7,2|7,3");
        	hqCoordinateMap.put(12, "8,2|8,3");
        	hqCoordinateMap.put(13, "9,2|9,3");
        	hqCoordinateMap.put(14, "10,2|10,3");
        	hqCoordinateMap.put(15, "4,4|4,5");
        	hqCoordinateMap.put(16, "5,4|5,5");
        	hqCoordinateMap.put(17, "6,4|6,5");
        	hqCoordinateMap.put(18, "7,4|7,5");
        	hqCoordinateMap.put(19, "8,4|8,5");
        	hqCoordinateMap.put(20, "9,4|9,5");
        	hqCoordinateMap.put(21, "10,4|10,5");
        	//开始写入数据
        	XWPFDocument document = new XWPFDocument(inputStream);
        	for (XWPFTable table : document.getTables()) {
           	    int tablePageIndex = document.getPosOfTable(table);
           	    if(tablePageIndex == 2) {
           	    	//名称
       	    		XWPFTableCell cell = table.getRow(0).getCell(1);
       	    		XWPFParagraph paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
       	    		XWPFRun run = paragraph.createRun();
       	    		run.setFontSize(12); //设置字体大小为12磅
       	    		//run.setBold(true); //设置加粗
       	    		run.setText(name);
       	    		//编号
       	    		cell = table.getRow(0).getCell(3);
       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
       	    		run = paragraph.createRun();
       	    		run.setFontSize(12);
       	    		run.setText(number);
       	    		//编制
       	    		cell = table.getRow(1).getCell(1);
       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
       	    		run = paragraph.createRun();
       	    		run.setFontSize(12);
       	    		run.setText(bz+" "+bzsj);
       	    		//校对
       	    		cell = table.getRow(1).getCell(3);
       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
       	    		run = paragraph.createRun();
       	    		run.setFontSize(12);
       	    		run.setText(jd+" "+jdsj);
       	    		//审查
       	    		cell = table.getRow(2).getCell(1);
       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
       	    		run = paragraph.createRun();
       	    		run.setFontSize(12);
       	    		run.setText(sh+" "+shsj);
       	    		//标审
       	    		cell = table.getRow(2).getCell(3);
       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
       	    		run = paragraph.createRun();
       	    		run.setFontSize(12);
       	    		run.setText(bs+" "+bssj);
       	    		//批准
       	    		cell = table.getRow(11).getCell(1);
       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
       	    		run = paragraph.createRun();
       	    		run.setFontSize(12);
       	    		run.setText(pz+" "+pzsj);
       	    		//会签
       	    		int amount = 1;
       	    		for (Object o : jsonArray) {
       	    			JSONObject jsonObj = (JSONObject) o;
       	    			for (String department : jsonObj.keySet()) {
    						JSONArray array = (JSONArray) jsonObj.get(department);
    						for (Object u : array) {
    							String user = (String) u;
    							String[] split = user.split("\\|");
    							String userName = split[0];
    							String time = split[1];
    							String[] coordinate = hqCoordinateMap.get(amount).split("\\|");
    							String[] departmentPosition = coordinate[0].split(",");
    							String[] userPosition = coordinate[1].split(",");
    							cell = table.getRow(Integer.parseInt(departmentPosition[0]))
    									.getCell(Integer.parseInt(departmentPosition[1]));
    		       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
    		       	    		run = paragraph.createRun();
    		       	    		run.setFontSize(12);
    		       	    		run.setText(department);
    		       	    		cell = table.getRow(Integer.parseInt(userPosition[0]))
    									.getCell(Integer.parseInt(userPosition[1]));
    		       	    		paragraph = cell.getParagraphs().size() > 0 ? cell.getParagraphs().get(0) : cell.addParagraph();
    		       	    		run = paragraph.createRun();
    		       	    		run.setFontSize(12);
    		       	    		run.setText(userName+" "+time);
    		       	    		amount++;
    						}
    					}
					}
           	    }
           	}
            document.write(outputStream);
            
            String targetName = "/orderTechnicalWord/orderTechnicalWord_" + number + ".docx";
            
            loggerBuffer.append(logFile.now()).append("  -->开始上传Minio").append("\n");
            loggerBuffer.append(logFile.now()).append("  -->上传Minio位置：").append(targetName).append("\n");

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
            targetPath = minioService.upload(byteArrayInputStream, targetName, 
            		"application/vnd.openxmlformats-officedocument.wordprocessingml.document");

            loggerBuffer.append(logFile.now()).append("  -->上传Minio地址:").append("\n");
            loggerBuffer.append(logFile.now()).append(targetPath).append("\n");

        } catch (Exception e) {
            logger.error("Word签名出错，详情请查看日志！\n", e);
            throw new Exception("Word签名出错，详情请查看日志！");
        }
        return targetPath;
    }
		
	/**
	 * 生成工艺更改单PDF逻辑
	 * @param loggerBuffer
	 * @param number
	 * @param processNumber
	 * @param processName
	 * @param model
	 * @param changeContent
	 * @param reason
	 * @param signInfo
	 * @param sendDepartment
	 * @return
	 * @throws Exception
	 */
	public String processChangePdf(StringBuffer loggerBuffer, String number, String processNumber, 
			String processName, String model, Object changeContent, String reason, 
			Object signInfo) throws Exception {
    	
        String targetPath = StringUtils.EMPTY;
        loggerBuffer.append(logFile.now()).append("  -->开始执行转PDF......").append("\n");

        try {
            //生成PDF文件
            ByteArrayOutputStream outputStream = generateProcessChangePdf(number, processNumber, 
            		processName, model, changeContent, reason, signInfo);
            
            String targetName = "/processChangePdf/processChangePdf_" + number + ".pdf";
            
            loggerBuffer.append(logFile.now()).append("  -->开始上传Minio").append("\n");
            loggerBuffer.append(logFile.now()).append("  -->上传Minio位置：").append(targetName).append("\n");

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
            targetPath = minioService.upload(byteArrayInputStream, targetName, "application/pdf");

            loggerBuffer.append(logFile.now()).append("  -->上传Minio地址:").append("\n");
            loggerBuffer.append(logFile.now()).append(targetPath).append("\n");

        } catch (Exception e) {
            logger.error("生成PDF出错，详情请查看日志！\n", e);
            throw new Exception("生成PDF出错，详情请查看日志！");
        }
        return targetPath;
    }
	
	/**
	 * 生成工艺更改单PDF
	 * @param number
	 * @param processNumber
	 * @param processName
	 * @param model
	 * @param changeContent
	 * @param reason
	 * @param signInfo
	 * @param sendDepartment
	 * @return
	 * @throws Exception
	 */
	public ByteArrayOutputStream generateProcessChangePdf(String number, String processNumber, 
			String processName, String model, Object changeContent, String reason, 
			Object signInfo) throws Exception {
		//确定总页数
		int page = 1;
		//存放每一页写入哪几条内容
		Map<Integer, List<Integer>> infoMap = Maps.newHashMap();
		List<Integer> preInfoList = Lists.newArrayList();
		List<Integer> afterInfoList = Lists.newArrayList();
		float preHeight = 193;
		float afterHeight = 193;
		//记录换页逻辑
		boolean flag = true;
		JSONArray changeContentArray = (JSONArray) changeContent;
		for (int orderNumber = 0; orderNumber < changeContentArray.size(); orderNumber++) {
			Object object = changeContentArray.get(orderNumber);
			JSONObject json = (JSONObject) object;
			for (String key : json.keySet()) {
				logger.info("最早的page:{}", page);
				if(StringUtils.contains(key, "preChangeContent")) {
					String str = (orderNumber+1)+"."+json.get(key);
					BigDecimal preCharactersLength = new BigDecimal(str.length());
					BigDecimal rows = preCharactersLength.divide(new BigDecimal("31"), 0, RoundingMode.UP);
					float rowsValue = rows.multiply(new BigDecimal(13)).floatValue();
					logger.info("preRowsValue:{}", rowsValue);
					preHeight = preHeight - rowsValue;
					logger.info("改前本页剩余高度容量preHeight:{}", preHeight);
					if(preHeight < 0 && preInfoList.isEmpty()) {
						if(flag) {
							flag = false;
							logger.info("空间不足，但强制插入了preInfoList一次数据。");
							preHeight = 193;
							afterHeight = 193;
							preInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							for (Integer integer : preInfoList) {
								logger.info("preInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							if((orderNumber+1) < changeContentArray.size()) page += 1;
							continue;
						}
					}else if(preHeight < 0) {
						if(flag) {
							flag = false;
							logger.info("本页空间不足，跳转至下一页");
							preHeight = 193;
							afterHeight = 193;
							List<Integer> list = Lists.newArrayList();
							preInfoList = preInfoList.size() >= afterInfoList.size() 
									? afterInfoList : preInfoList;
							for (Integer integer : preInfoList) {
								logger.info("preInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							page += 1;
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							orderNumber -= 1;
							continue;
						}
					}else if((orderNumber+1) >= changeContentArray.size()) {
						if(flag) {
							flag = false;
							logger.info("没有下一条内容了，直接插入");
							preInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							preInfoList = preInfoList.size() >= afterInfoList.size() 
									? preInfoList : afterInfoList;
							for (Integer integer : preInfoList) {
								logger.info("preInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							continue;
						}
					}else if(preHeight >= 0) {
						logger.info("空间充裕，插入了preInfoList一次数据。");
						preInfoList.add(orderNumber+1);
					}
				}else if(StringUtils.contains(key, "afterChangeContent")) {
					String str = (orderNumber+1)+"."+json.get(key);
					BigDecimal preCharactersLength = new BigDecimal(str.length());
					BigDecimal rows = preCharactersLength.divide(new BigDecimal("31"), 0, RoundingMode.UP);
					float rowsValue = rows.multiply(new BigDecimal(13)).floatValue();
					logger.info("afterRowsValue:{}", rowsValue);
					afterHeight = afterHeight - rowsValue;
					logger.info("改后本页剩余高度容量afterHeight:{}", afterHeight);
					if(afterHeight < 0 && afterInfoList.isEmpty()) {
						if(flag) {
							flag = false;
							logger.info("空间不足，但强制插入了afterInfoList一次数据。");
							preHeight = 193;
							afterHeight = 193;
							afterInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							for (Integer integer : afterInfoList) {
								logger.info("afterInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							if((orderNumber+1) < changeContentArray.size()) page += 1;
							continue;
						}
					}else if(afterHeight < 0) {
						if(flag) {
							flag = false;
							logger.info("本页空间不足，跳转至下一页");
							preHeight = 193;
							afterHeight = 193;
							List<Integer> list = Lists.newArrayList();
							afterInfoList = preInfoList.size() >= afterInfoList.size() 
									? afterInfoList : preInfoList;
							for (Integer integer : afterInfoList) {
								logger.info("afterInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							page += 1;
							preInfoList = Lists.newArrayList();
							afterInfoList = Lists.newArrayList();
							orderNumber -= 1;
							continue;
						}
					}else if((orderNumber+1) >= changeContentArray.size()) {
						if(flag) {
							flag = false;
							logger.info("没有下一条内容了，直接插入");
							afterInfoList.add(orderNumber+1);
							List<Integer> list = Lists.newArrayList();
							afterInfoList = preInfoList.size() >= afterInfoList.size() 
									? preInfoList : afterInfoList;
							for (Integer integer : afterInfoList) {
								logger.info("afterInfoList:{}", integer);
								list.add(integer);
							}
							logger.info("当前page:{}", page);
							infoMap.put(page, list);
							continue;
						}
					}else if(afterHeight >= 0) {
						logger.info("空间充裕，插入了afterInfoList一次数据。");
						afterInfoList.add(orderNumber+1);
					}
				}
    		}
			flag = true;
		}
		
		for (Integer integer : infoMap.keySet()) {
			List<Integer> list = infoMap.get(integer);
			for (Integer i : list) {
				logger.info("infoMap:{}", "第"+integer+"页中需要写入的条目为"+i);
			}
		}
		
		//更改形式获取
		String model1 = "□ 单页更换";
		String model2 = "□ 整册换版";
		if(StringUtils.isNotEmpty(model)) {
			if(StringUtils.equals(model, "单页更换")) {
				model1 = "■ 单页更换";
			}else if(StringUtils.equals(model, "整册换版")) {
				model2 = "■ 整册换版";
			}
		}
		
		//签名信息获取
		String bz = "";
		String bzsj = "";
		String jd = "";
		String jdsj = "";
		String sh = "";
		String shsj = "";
		String pz = "";
		String pzsj = "";
		for (Object object : (JSONArray) signInfo) {
			JSONObject json = (JSONObject) object;
			for (String key : json.keySet()) {
				String str = (String) json.get(key);
				String[] split = str.split("\\|");
				switch (key) {
				case "bz":
					bz = split[0];
					bzsj = split[1];
					break;
				case "jd":
					jd = split[0];
					jdsj = split[1];
					break;
				case "sh":
					sh = split[0];
					shsj = split[1];
					break;
				case "pz":
					pz = split[0];
					pzsj = split[1];
					break;
				}
    		}
		}
		
		//开始生成PDF
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		Document document = new Document();
    	document.setPageSize(PageSize.A4.rotate());//横版
    	PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
		
		document.open();
		
		logger.info("page:{}", page);
		for(int i = 1; i <= page; i++) {
			Paragraph header = new Paragraph("工艺文件更改通知单", HEAD_FONT);
			header.setAlignment(Element.ALIGN_CENTER);
			document.add(header);
			
			header = new Paragraph("FR010206-01\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020", FONT);
			header.setAlignment(Element.ALIGN_RIGHT);
			document.add(header);
			
			header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			PdfPTable table = new PdfPTable(9);
			float[] cellsWidth = {104f, 104f, 104f, 48f, 50f, 54f, 50f, 104f, 104f};
			table.setWidths(cellsWidth);// 单元格宽度
			table.setSplitLate(false);
			table.setWidthPercentage(100);
			
			table.addCell(createCell("更改单号：", 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(number, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("更改形式：", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(model1 +" "+ model2, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("工艺文件编号：", 34f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(processNumber, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("工艺文件名称：", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(processName, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("更改原因："+reason, 41f, 9, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT));
			
			//更改内容获取
			Paragraph preParagraph = new Paragraph();
			Paragraph afterParagraph = new Paragraph();
			Chunk preChunk = new Chunk("更改前：\n");
			preChunk.setFont(FONT);
			preParagraph.add(preChunk);
			Chunk afterChunk = new Chunk("更改后：\n");
			afterChunk.setFont(FONT);
	        afterParagraph.add(afterChunk);
	        //获取到本页需要写入哪几条更改内容
	        List<Integer> list = infoMap.get(i);
	        logger.info("i:{}", i);
	        for (Integer integer : list) {
				for (Object object : (JSONArray) changeContent) {
					JSONObject json = (JSONObject) object;
					for (String key : json.keySet()) {
						if(StringUtils.equals(key, "preChangeContent"+integer)) {
							preChunk = new Chunk(integer+"."+json.get(key)+"\n");
							preChunk.setFont(FONT);
							preParagraph.add(preChunk);
						}else if(StringUtils.equals(key, "afterChangeContent"+integer)) {
							afterChunk = new Chunk(integer+"."+json.get(key)+"\n");
							afterChunk.setFont(FONT);
					        afterParagraph.add(afterChunk);
						}
		    		}
				}
			}
	        
			PdfPCell preCell = createCell("", 193f, 4, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT);
			preCell.addElement(preParagraph);
			table.addCell(preCell);
			
			PdfPCell afterCell = createCell("", 0, 5, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT);
			afterCell.addElement(afterParagraph);
			table.addCell(afterCell);
			
			table.addCell(createCell("审批栏", 19f, 9, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("编制："+bz+" "+bzsj+"\u0020\u0020校对："+jd+" "+jdsj+"\u0020\u0020审核："
					+sh+" "+shsj+"\u0020\u0020批准："+pz+" "+pzsj, 30f, 9, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("工艺文件回收/发放记录", 19f, 9, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("部门", 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("档案室", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("生产部", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("回收签字/日期", 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("发放签字/日期", 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			document.add(table);
			
			header = new Paragraph("\u0020\u0020\u0020注："
					+ "1.档案室负责文件的回收、更改与发放工作。"
					+ "2.本更改单自负责人签字批准后方可实施。"
					+ "3.工艺文件回收/发放记录需由各部门经办人签字确认。", SMALL_FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph("第"+i+"页 共"+page+"页", SMALL_FONT);
			header.setAlignment(Element.ALIGN_CENTER);
			document.add(header);
			
			//有下一页，新生成一页PDF
			if(i+1 <= page) {
				document.newPage();
			}
		}
		
		document.close();
		
		return baos;
	}
	
	/**
	 * 生成生产领用配套单逻辑
	 * @param loggerBuffer
	 * @param basicInfo
	 * @param contents
	 * @return
	 * @throws Exception
	 */
	public String productionSupportingPdf(StringBuffer loggerBuffer, String basicInfo, 
			Object contents) throws Exception {
    	
        String targetPath = StringUtils.EMPTY;
        loggerBuffer.append(logFile.now()).append("  -->开始执行转PDF......").append("\n");

        try {
        	String[] split = basicInfo.split("\\|");
            //生成PDF文件
            ByteArrayOutputStream outputStream = generateProductionSupportingPdf(basicInfo, contents);
            
            String targetName = "/productionSupportingPdf/productionSupportingPdf_" + split[2] + ".pdf";
            
            loggerBuffer.append(logFile.now()).append("  -->开始上传Minio").append("\n");
            loggerBuffer.append(logFile.now()).append("  -->上传Minio位置：").append(targetName).append("\n");

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
            targetPath = minioService.upload(byteArrayInputStream, targetName, "application/pdf");

            loggerBuffer.append(logFile.now()).append("  -->上传Minio地址:").append("\n");
            loggerBuffer.append(logFile.now()).append(targetPath).append("\n");

        } catch (Exception e) {
            logger.error("生成PDF出错，详情请查看日志！\n", e);
            throw new Exception("生成PDF出错，详情请查看日志！");
        }
        return targetPath;
    }
	
	/**
	 * 生成生产领用配套单PDF
	 * @param basicInfo
	 * @param contents
	 * @return
	 * @throws Exception
	 */
	public ByteArrayOutputStream generateProductionSupportingPdf(String basicInfo, Object contents) 
			throws Exception {
		//表头信息
		String[] split = basicInfo.split("\\|");
		String model = split[0];
		String name = split[1];
		String partNumber = split[2];
		
		//需要写入表格的数据
		List<Map<String, String>> infoList = Lists.newArrayList();
		for (Object object : (JSONArray) contents) {
			JSONObject json = (JSONObject) object;
			Map<String, String> map = Maps.newHashMap();
			map.put("name", (String) json.get("name"));//零件名称
			map.put("number", (String) json.get("number"));//零件编号
			map.put("amount", (String) json.get("amount"));//使用数量
			map.put("unit", (String) json.get("unit"));//单位
			map.put("remark", (String) json.get("remark"));//备注
			infoList.add(map);
		}
			
		//开始生成PDF
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		Document document = new Document();
		document.setPageSize(PageSize.A4);
		PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
		document.open();
		
		//页码
		int i = 1;
		//序号
		int j = 0;
		//判断是否有续页
		boolean flag = true;
		while(flag) {
			//记录表格剩余高度
			float totalHeight = 530f;
			Paragraph header = new Paragraph("生产领用配套单", HEAD_FONT);
			header.setAlignment(Element.ALIGN_CENTER);
			document.add(header);
			
			header = new Paragraph("FR010203-01\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020", FONT);
			header.setAlignment(Element.ALIGN_RIGHT);
			document.add(header);
			
			header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			PdfPTable table = new PdfPTable(8);
			float[] cellsWidth = {29f, 113f, 57f, 61f, 70f, 32f, 32f, 89f};
			table.setWidths(cellsWidth);// 单元格宽度
			table.setSplitLate(false);
			table.setWidthPercentage(100);
			
			table.addCell(createCell("型号", 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(model, 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("型别", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("发动机编号", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("名称", 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(name, 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("部件编号", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("部件件号", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell(partNumber, 0, 3, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("", 6f, 8, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("序号", 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("名称", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("规格型号/图号", 0, 2, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("编号/批次", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("数量", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("单位", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			table.addCell(createCell("备注", 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
			
			document.add(table);
			
			//循环必须将本页的空白占满，不管格子里有没有内容
			while(true) {
				table = new PdfPTable(8);
				table.setWidths(cellsWidth);
				table.setSplitLate(false);
				table.setWidthPercentage(100);
				
				Map<String, String> map = Maps.newHashMap();
				try {
					map = infoList.get(j);
				}catch (IndexOutOfBoundsException e) {
					//没有续页了
					flag = false;
				}
				
				table.addCell(createCell(map.get("name") == null?"":++j+""
						, 19f, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
				
				table.addCell(createCell(map.get("name") == null?"":map.get("name")
						, 0, 1, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
				
				table.addCell(createCell(map.get("number") == null?"":map.get("number")
						, 0, 2, 1, Element.ALIGN_LEFT, Element.ALIGN_MIDDLE, FONT));
				
				table.addCell(createCell("", 0, 1, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT));
				
				table.addCell(createCell(map.get("amount") == null?"":map.get("amount")
						, 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
				
				table.addCell(createCell(map.get("unit") == null?"":map.get("unit")
						, 0, 1, 1, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, FONT));
				
				table.addCell(createCell(map.get("remark") == null?"":map.get("remark")
						, 0, 1, 1, Element.ALIGN_LEFT, Element.ALIGN_TOP, FONT));
				
				document.add(table);
				totalHeight = totalHeight - table.getTotalHeight();
				System.out.println("第"+i+"页剩余表格高度为"+totalHeight);
				if(totalHeight <= 0) break;
			}
			
			header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph("\u0020\u0020\u0020计调员："
					+ "\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020"
					+ "\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020库管员："
					+ "\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020"
					+ "\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020领用人：", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph(" ", FONT);
			header.setAlignment(Element.ALIGN_LEFT);
			document.add(header);
			
			header = new Paragraph("第"+i+"页", SMALL_FONT);
			header.setAlignment(Element.ALIGN_CENTER);
			document.add(header);
			
			//有下一页，新生成一页PDF
			if(flag) {
				document.newPage();
				i++;
			}
		}
		
		document.close();
		
		return baos;
	}
}
